## 5. 数据结构

### 5.1 列表的更多特性

l = [1, 2, 3, 4]

l.append(5)                     # 追加
print(l)

l.extend([7, 8])                # 扩展  : 可迭代对象中的所有元素
print(l)

l.insert(5,6)                   # 指定位置插入元素
print(l)

l.remove(8)
print(l)

i = l.pop()                     # 删除指定索引, 不指定删除最后一个, 并返回删除的对象
print(i)
print(l)

print("对象 5 的索引: " , l.index(3))

l.append(6)
print("对象 6 出现的次数", l.count(6))

l.sort(reverse=True)

print("排序 reverse: ", l)


l_copy = l.copy()
print("浅拷贝 l_copy : ", l_copy)

print("浅拷贝 l_copy clear 后 : ", l_copy)

l.clear()
print(l)

#### 5.1.1. 列表作为栈使用  (后进先出)

stack = [3, 4, 5]
print("追加前: ", stack)
stack.append(6)
stack.append(7)
print("追加后: " ,stack)
print(stack.pop())
print(stack.pop())

#### 5.1.2. 列表作为队列使用 (先进先出)

from collections import deque
queue = deque(["Eric", "John", "Michael"])
print("追加前: ", queue)
queue.append('Terry')
print("追  加: ", queue)
queue.append('Graham')
print("追  加: ", queue)

print("先  出: ", queue.popleft())
print("先出后: ",  queue)
print("先  出: ", queue.popleft())
print("先出后: ",  queue)

#### 5.1.3. 列表推导式
'''列表推导式
提供了一个更简单的创建列表的方法。
'''

squares = []
for x in range(10):
    squares.append(x**2)
print("方格: ", squares)
print("x 在 for 循环后仍然存在", x)

squares2 = list(map(lambda x: x**2, range(10)))
print("推导式1: ", squares2)
squares3 = [x**2 for x in range(10)]
print("推导式2: ", squares3)


a = [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
print(a)
print("等价于: TODO")

from math import pi
b =  [str(round(pi, i)) for i in range(1, 6)]
print("使用复杂的表达式和嵌套函数: ", b)

#### 5.1.4. 嵌套的列表推导式

### 5.2 del 语句

a = [-1, 1, 66.25, 333, 333, 1234.5]
print("a: ", a)
del a[0]
print("del a[0]: ", a)
del a
#print("del a: ", a)             # NameError: name 'a' is not defined

### 5.3 元组和序列

'''序列 数据类型
被逗号隔开的值组成
'''

t = 12345, 54321, 'hello'
print("t: ", t)
u = t, (1,2,3,4,5)              # Tuples may be nested:
print("u: ",u)
#t[0] = 8889                     # Tuples are immutable:

'''列表与元组
列表是 mutable, 一般类型相同, 迭代访问
元组是 immutable , namedTuples, 解包或索引访问
'''

empty = ()
singleton = 'hello',
print("0 个元素数组: ", empty, len(empty), sep='   |   ')
print("1 个元素数组: ", singleton, len(singleton), sep='   |   ')

'''序列解包 '''
print("序列解包: ", t)
x,y,z = t
print("解包: x=%d, y=%d z=%s" %(x, y, z ))

### 5.4 集合
'''不重复元素组成的无序的集
基本用法: 成员检测 , 消除重复
'''

'''空集合: 用 set(),  而不能用 {} 与字典混淆'''

s = set()
print("空集合: ", s)

a = set('aab')
b = set('kjjlka')

print("a: ", a)
print("b: ", b)

print("a - b: ", a - b)             # in a but not in b
print("a | b: ", a | b)             # or
print("a & b: ", a & b)             # and
print("a ^ b: ", a ^ b)             # in a or b  but not both

### 5.5 字典 dict
'''
联合内存, 联合数组
关键字索引
'''

tel = {'jack': 4098, 'sape': 4139}
tel['guido'] = 4217
print(tel)

emptyList = {}
print("empty list : ", emptyList)

'''字典主要的操作是使用关键字存储和解析值
'''

del tel['jack']
print("del list : ", tel)

print("list keys: " , list(tel))

sorted(tel, reverse=False)
print("sorted: ", tel)

d = dict([('sape', 499), ('guido', 43444)])
d2 = dict(sape=444, guido=1232)
print("dict() : ", d)
print("dict() : ", d2)

### 5.6 循环的技巧
'''
(1,2) 元组
[1,2] 列表
{1,2} 集合 set
{k:v} 字典
'''

'''字典循环
'''
knights = {'gallahad': 'the pure', 'robin': 'the brawe'}
for k, v in knights.items():
    print(k, v)

'''序列循环
'''
for i, v in enumerate(['tic', 'tac', 'toe']):
    print(i, v)

'''当同时在两个或更多序列中循环时，
可以用 zip() 函数将其内元素一一匹配。
'''

questions = ['name', 'quest', 'favorite color']
answers = ['lancelot', 'the holy grail', 'blue']
zip_iter = zip(questions, answers)  # [(name, lancelot), (quest, the holy grail), (favorite, blue)]

for q, a in zip(questions, answers):
    print('What\'s your {0} ? It\'s {1}.'.format(q, a))

''' 逆向循环一个序列
reversed()
'''
for i in reversed(range(1, 10, 2)):
    print(i, end=',')
print()

'''循环时修改列表内容
改为创建新列表
'''
import math
raw_data = [56.2, float('NaN'), 51.7, 55.3, 52.5, float('NaN'), 47.8]
filter_data = []
for v in raw_data:
    if not math.isnan(v):
        filter_data.append(v)
print("src data : ", raw_data)
print("filter data: ", filter_data)

### 5.7, 深入条件控制
''' while  , if
比较操作符
in  , not in               在或不在一个序列 
is  , is not                是或不是同一对象

比较操作符 可以传递
a < b == c                  会校验是否 a 小于 b 并且 b 等于

and , or 
A and not B or C             等价于 (A and (not B)) or C

短路 运算符
 A 和 C 为真而 B 为假，那么 A and B and C 不会解析 C

Python 与 C 不同，在表达式内部赋值必须显式地使用 海象运算符 := 来完成

优先级
数值运算  > 比较操作符  > 布尔运算符(  not > and > or )
'''

### 5.8. 比较序列和其他类型
'''序列对象通常可以与相同序列类型的其他对象比较
字典式 顺序

对字符串来 字典式顺序是使用 Unicode 码位序号对单个字符排序

不同类型可能抛出类型异常  TypeError  
'''
print((1,2,3) < (1,2,3))                # False  (元组)
print([1,2,3] < [1,2,3])                # False  (列表)

print('ABC' < 'C' < 'Pascal' < 'Python') # True
